package com.nnnu.wsnackshop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nnnu.wsnackshop.mapper.*;
import com.nnnu.wsnackshop.pojo.entity.*;
import com.nnnu.wsnackshop.service.IDashboardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 仪表盘数据服务实现类
 */
@Service
public class DashboardServiceImpl implements IDashboardService {

    private final OrdersMapper ordersMapper;
    private final MembersMapper membersMapper;
    private final CouponUsageMapper couponUsageMapper;
    private final CategoriesMapper categoriesMapper;
    private final ProductsMapper productsMapper;
    private final ProductSkuMapper productSkuMapper;
    private final UsersMapper userMapper;
    private final OrderItemsMapper orderItemsMapper;

    @Autowired
    public DashboardServiceImpl(OrdersMapper ordersMapper,
            MembersMapper membersMapper,
            CouponUsageMapper couponUsageMapper,
            CategoriesMapper categoriesMapper,
            ProductsMapper productsMapper,
            ProductSkuMapper productSkuMapper,
            UsersMapper userMapper,
            OrderItemsMapper orderItemsMapper) {
        this.ordersMapper = ordersMapper;
        this.membersMapper = membersMapper;
        this.couponUsageMapper = couponUsageMapper;
        this.categoriesMapper = categoriesMapper;
        this.productsMapper = productsMapper;
        this.productSkuMapper = productSkuMapper;
        this.userMapper = userMapper;
        this.orderItemsMapper = orderItemsMapper;
    }

    /**
     * 获取仪表盘统计数据
     * 
     * @return 统计数据，包括今日订单数、总用户数、总收入和优惠券使用数等
     */
    @Override
    public Map<String, Object> getDashboardStats() {
        Map<String, Object> result = new HashMap<>();

        // 获取今天的开始和结束时间
        LocalDate today = LocalDate.now();
        LocalDateTime startOfToday = today.atStartOfDay();
        LocalDateTime endOfToday = today.plusDays(1).atStartOfDay().minusSeconds(1);

        // 获取昨天的开始和结束时间
        LocalDate yesterday = today.minusDays(1);
        LocalDateTime startOfYesterday = yesterday.atStartOfDay();
        LocalDateTime endOfYesterday = yesterday.plusDays(1).atStartOfDay().minusSeconds(1);

        // 1. 今日订单数
        long todayOrderCount = ordersMapper.selectCount(
                new LambdaQueryWrapper<Orders>()
                        .between(Orders::getCreatedAt, startOfToday, endOfToday));
        // 昨日订单数
        long yesterdayOrderCount = ordersMapper.selectCount(
                new LambdaQueryWrapper<Orders>()
                        .between(Orders::getCreatedAt, startOfYesterday, endOfYesterday));

        // 计算订单增长趋势
        double orderCountTrend = 0;
        if (yesterdayOrderCount > 0) {
            orderCountTrend = (double) (todayOrderCount - yesterdayOrderCount) / yesterdayOrderCount * 100;
        }

        // 2. 总用户数
        long totalUserCount = membersMapper.selectCount(null);

        // 昨日总用户数
        long yesterdayUserCount = membersMapper.selectCount(
                new LambdaQueryWrapper<Members>()
                        .lt(Members::getCreatedAt, startOfToday));

        // 计算用户增长趋势
        double userCountTrend = 0;
        if (yesterdayUserCount > 0) {
            userCountTrend = (double) (totalUserCount - yesterdayUserCount) / yesterdayUserCount * 100;
        }

        // 3. 总收入
        BigDecimal totalRevenue = ordersMapper.selectTotalRevenue();

        // 昨日总收入
        BigDecimal yesterdayRevenue = ordersMapper.selectTotalRevenueBefore(startOfToday);

        // 计算收入增长趋势
        double revenueTrend = 0;
        if (yesterdayRevenue != null && yesterdayRevenue.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal diff = totalRevenue.subtract(yesterdayRevenue);
            revenueTrend = diff.divide(yesterdayRevenue, 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100))
                    .doubleValue();
        }

        // 4. 纯利润（总收入减去成本）
        BigDecimal netProfit = ordersMapper.selectNetProfit();

        // 5. 优惠券使用数
        long couponUsageCount = couponUsageMapper.selectCount(null);

        // 昨日优惠券使用数
        long yesterdayCouponUsageCount = couponUsageMapper.selectCount(
                new LambdaQueryWrapper<CouponUsage>()
                        .lt(CouponUsage::getCreatedAt, startOfToday));

        // 计算优惠券使用增长趋势
        double couponUsageTrend = 0;
        if (yesterdayCouponUsageCount > 0) {
            couponUsageTrend = (double) (couponUsageCount - yesterdayCouponUsageCount) / yesterdayCouponUsageCount
                    * 100;
        }

        // 封装结果
        result.put("todayOrderCount", todayOrderCount);
        result.put("orderCountTrend", Math.round(orderCountTrend * 10) / 10.0); // 保留一位小数

        result.put("totalUserCount", totalUserCount);
        result.put("userCountTrend", Math.round(userCountTrend * 10) / 10.0);

        result.put("totalRevenue", totalRevenue);
        result.put("revenueTrend", Math.round(revenueTrend * 10) / 10.0);

        // 添加纯利润字段
        result.put("netProfit", netProfit);

        result.put("couponUsageCount", couponUsageCount);
        result.put("couponUsageTrend", Math.round(couponUsageTrend * 10) / 10.0);

        return result;
    }

    /**
     * 获取销售趋势数据
     * 
     * @param timeRange 时间范围：'day', 'week', 'month', 'year'
     * @return 销售趋势数据
     */
    @Override
    public List<Map<String, Object>> getSalesTrend(String timeRange) {
        List<Map<String, Object>> result = new ArrayList<>();

        LocalDateTime startTime;
        LocalDateTime endTime = LocalDateTime.now();
        DateTimeFormatter formatter;
        String groupFormat;

        // 根据时间范围确定查询的开始时间和日期格式
        switch (timeRange) {
            case "day":
                // 今天每小时的销售数据
                startTime = LocalDate.now().atStartOfDay();
                formatter = DateTimeFormatter.ofPattern("HH:00");
                groupFormat = "%H:00";
                break;
            case "week":
                // 最近7天的销售数据（不再是本周星期一开始，而是往前推7天）
                startTime = LocalDate.now().minusDays(6).atStartOfDay(); // 今天算一天，所以减6天
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                groupFormat = "%m-%d";
                break;
            case "month":
                // 本月每天的销售数据
                startTime = LocalDate.now().withDayOfMonth(1).atStartOfDay();
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                groupFormat = "%m-%d";
                break;
            case "year":
                // 今年每月的销售数据
                startTime = LocalDate.now().withDayOfYear(1).atStartOfDay();
                formatter = DateTimeFormatter.ofPattern("yyyy-MM");
                groupFormat = "%Y-%m";
                break;
            default:
                // 默认为最近7天
                startTime = LocalDate.now().minusDays(6).atStartOfDay();
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                groupFormat = "%m-%d";
                break;
        }

        // 查询销售数据
        List<Map<String, Object>> salesData = ordersMapper.selectSalesTrend(
                Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()),
                groupFormat);

        // 如果是按天查询，需要填充没有销售数据的日期
        if (timeRange.equals("day")) {
            // 生成24小时的时间点
            Map<String, Object> hourlyData = new LinkedHashMap<>();
            for (int i = 0; i < 24; i++) {
                String hour = String.format("%02d:00", i);
                hourlyData.put(hour, 0.0);
            }

            // 填充销售数据
            for (Map<String, Object> data : salesData) {
                String date = (String) data.get("date");
                Double amount = ((Number) data.get("amount")).doubleValue();
                hourlyData.put(date, amount);
            }

            // 转换为结果格式
            for (Map.Entry<String, Object> entry : hourlyData.entrySet()) {
                Map<String, Object> item = new HashMap<>();
                item.put("date", entry.getKey());
                item.put("amount", entry.getValue());
                result.add(item);
            }
        } else if (timeRange.equals("week")) {
            // 生成最近7天每天的日期
            Map<String, Object> dailyData = new LinkedHashMap<>();
            LocalDate start = startTime.toLocalDate();
            for (int i = 0; i < 7; i++) {
                String date = start.plusDays(i).format(formatter);
                dailyData.put(date, 0.0);
            }

            // 填充销售数据
            for (Map<String, Object> data : salesData) {
                String date = (String) data.get("date");
                Double amount = ((Number) data.get("amount")).doubleValue();
                dailyData.put(date, amount);
            }

            // 转换为结果格式
            for (Map.Entry<String, Object> entry : dailyData.entrySet()) {
                Map<String, Object> item = new HashMap<>();
                item.put("date", entry.getKey());
                item.put("amount", entry.getValue());
                result.add(item);
            }
        } else {
            // 直接使用查询结果
            result = salesData;
        }

        return result;
    }

    /**
     * 获取销售分类占比数据
     * 
     * @param timeRange 时间范围：'day', 'week', 'month', 'year'
     * @return 各分类销售占比数据
     */
    @Override
    public List<Map<String, Object>> getCategorySales(String timeRange) {
        LocalDateTime startTime;
        LocalDateTime endTime = LocalDateTime.now();

        // 根据时间范围确定查询的开始时间
        startTime = switch (timeRange) {
            case "day" ->
                // 今天的销售数据
                LocalDate.now().atStartOfDay();
            case "week" ->
                // 最近7天的销售数据
                LocalDate.now().minusDays(6).atStartOfDay(); // 今天算一天，所以减6天
            case "month" ->
                // 本月的销售数据
                LocalDate.now().withDayOfMonth(1).atStartOfDay();
            case "year" ->
                // 今年的销售数据
                LocalDate.now().withDayOfYear(1).atStartOfDay();
            default ->
                // 默认为最近7天
                LocalDate.now().minusDays(6).atStartOfDay();
        };

        // 查询分类销售数据
        List<Map<String, Object>> categorySalesData = ordersMapper.selectCategorySales(
                Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()));

        // 如果没有数据，返回空列表
        if (categorySalesData == null || categorySalesData.isEmpty()) {
            return new ArrayList<>();
        }

        // 计算总销售额
        double totalSales = categorySalesData.stream()
                .mapToDouble(data -> ((Number) data.get("salesAmount")).doubleValue())
                .sum();

        // 计算每个分类的销售占比
        for (Map<String, Object> data : categorySalesData) {
            double salesAmount = ((Number) data.get("salesAmount")).doubleValue();
            double percentage = totalSales > 0 ? (salesAmount / totalSales) * 100 : 0;
            data.put("percentage", Math.round(percentage * 10) / 10.0); // 保留一位小数
        }

        return categorySalesData;
    }

    /**
     * 获取最近订单数据
     * 
     * @param limit 获取的订单数量
     * @return 最近订单列表
     */
    @Override
    public List<Map<String, Object>> getRecentOrders(int limit) {
        // 查询最近的订单
        List<Orders> recentOrders = ordersMapper.selectRecentOrders(limit);

        // 转换为前端需要的格式
        List<Map<String, Object>> result = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        for (Orders order : recentOrders) {
            Map<String, Object> orderMap = new HashMap<>();
            orderMap.put("id", order.getId());
            orderMap.put("orderNo", order.getOrderNo());

            // 获取用户信息，替换显示用户ID的问题
            Integer userId = order.getUserId();
            String customerName = "未知用户";
            if (userId != null) {
                Users user = userMapper.selectById(userId);
                if (user != null) {
                    customerName = user.getNickname() != null ? user.getNickname() : user.getUsername();
                }
            }
            orderMap.put("customerName", customerName);

            orderMap.put("totalAmount", order.getTotalAmount());
            orderMap.put("status", order.getOrderStatus());
            orderMap.put("statusText", getOrderStatusText(String.valueOf(order.getOrderStatus()))); // 转换为String

            orderMap.put("createTime", order.getCreatedAt() != null ? order.getCreatedAt().format(formatter) : null);

            result.add(orderMap);
        }

        return result;
    }

    /**
     * 获取热门商品数据
     * 
     * @param limit 获取的商品数量
     * @return 热门商品列表
     */
    @Override
    public List<Map<String, Object>> getHotProducts(int limit) {
        // 查询销量最高的商品
        List<Products> hotProducts = productsMapper.selectHotProducts(limit);

        // 转换为前端需要的格式
        List<Map<String, Object>> result = new ArrayList<>();

        for (Products product : hotProducts) {
            Map<String, Object> productMap = new HashMap<>();
            productMap.put("id", product.getId());
            productMap.put("name", product.getName());
            productMap.put("image", product.getMainImage());

            // 查询该商品的SKU价格和库存信息
            QueryWrapper<ProductSku> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("product_id", product.getId());
            queryWrapper.orderByAsc("price");
            List<ProductSku> skuList = productSkuMapper.selectList(queryWrapper);

            // 修改库存计算逻辑，使用单个SKU的库存值而不是累加
            BigDecimal minPrice = null;
            int stockCount = 0;

            if (!skuList.isEmpty()) {
                // 获取首个SKU作为展示
                ProductSku firstSku = skuList.get(0);
                if (firstSku.getStock() != null) {
                    stockCount = firstSku.getStock();
                }

                // 依然查找最低价格SKU
                for (ProductSku sku : skuList) {
                    if (minPrice == null || (sku.getPrice() != null && sku.getPrice().compareTo(minPrice) < 0)) {
                        minPrice = sku.getPrice();
                    }
                }

                productMap.put("price", minPrice != null ? minPrice : BigDecimal.ZERO);
            } else {
                productMap.put("price", BigDecimal.ZERO);
            }

            // 设置库存和销量
            productMap.put("stockCount", stockCount);

            // 从查询结果中获取销量
            Integer salesCount = null;
            try {
                // 尝试从查询结果中获取sales_count字段
                Field field = Products.class.getDeclaredField("salesCount");
                field.setAccessible(true);
                salesCount = (Integer) field.get(product);

                // 如果反射获取到的值为null，使用orderItemsMapper直接查询
                if (salesCount == null) {
                    salesCount = orderItemsMapper.getProductSales(product.getId());
                }
            } catch (Exception e) {
                // 如果反射获取失败，直接查询
                salesCount = orderItemsMapper.getProductSales(product.getId());
            }

            productMap.put("salesCount", salesCount != null ? salesCount : 0);

            result.add(productMap);
        }

        return result;
    }

    /**
     * 获取用户增长数据
     * 
     * @param timeRange 时间范围：'week', 'month', 'year'
     * @return 用户增长的时间序列数据
     */
    @Override
    public List<Map<String, Object>> getUserGrowth(String timeRange) {
        LocalDateTime startTime;
        LocalDateTime endTime = LocalDateTime.now();
        DateTimeFormatter formatter;
        String groupFormat;

        // 根据时间范围确定查询的开始时间和日期格式
        switch (timeRange) {
            case "week":
                // 最近7天的用户增长
                startTime = LocalDate.now().minusDays(6).atStartOfDay(); // 今天算一天，所以减6天
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                groupFormat = "%m-%d";
                break;
            case "month":
                // 本月每天的用户增长
                startTime = LocalDate.now().withDayOfMonth(1).atStartOfDay();
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                groupFormat = "%m-%d";
                break;
            case "year":
                // 今年每月的用户增长
                startTime = LocalDate.now().withDayOfYear(1).atStartOfDay();
                formatter = DateTimeFormatter.ofPattern("yyyy-MM");
                groupFormat = "%Y-%m";
                break;
            default:
                // 默认为本月
                startTime = LocalDate.now().withDayOfMonth(1).atStartOfDay();
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                groupFormat = "%m-%d";
                break;
        }

        // 查询用户增长数据
        List<Map<String, Object>> userGrowthData = membersMapper.selectUserGrowth(
                Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()),
                groupFormat);

        // 如果是按周查询，需要填充没有用户增长的日期
        if (timeRange.equals("week")) {
            // 生成最近7天每天的日期
            Map<String, Object> dailyData = new LinkedHashMap<>();
            LocalDate start = startTime.toLocalDate();
            for (int i = 0; i < 7; i++) {
                String date = start.plusDays(i).format(formatter);
                dailyData.put(date, 0);
            }

            // 填充用户增长数据
            for (Map<String, Object> data : userGrowthData) {
                String date = (String) data.get("date");
                Integer count = ((Number) data.get("count")).intValue();
                dailyData.put(date, count);
            }

            // 转换为结果格式
            List<Map<String, Object>> result = new ArrayList<>();
            for (Map.Entry<String, Object> entry : dailyData.entrySet()) {
                Map<String, Object> item = new HashMap<>();
                item.put("date", entry.getKey());
                item.put("count", entry.getValue());
                result.add(item);
            }

            return result;
        } else {
            // 直接使用查询结果
            return userGrowthData;
        }
    }

    /**
     * 获取订单状态文本
     * 
     * @param status 订单状态
     * @return 订单状态文本
     */
    private String getOrderStatusText(String status) {
        if (status == null)
            return "未知";

        // 将数字状态转换为对应的中文状态
        try {
            int statusCode = Integer.parseInt(status);
            return switch (statusCode) {
                case 0 -> "待付款"; // pending
                case 1 -> "待发货"; // paid
                case 2 -> "备货中"; // packing
                case 3 -> "配送中"; // delivering
                case 4 -> "已完成"; // completed
                case 5 -> "已取消"; // cancelled
                case 6 -> "待确认收货"; // delivered
                case 7 -> "待自提"; // ready_for_pickup
                case 8 -> "已退款"; // refunded
                default -> "未知";
            };
        } catch (NumberFormatException e) {
            // 如果不是数字，尝试按旧的字符串格式处理
            return switch (status) {
                case "pending" -> "待付款";
                case "paid" -> "待发货";
                case "shipping" -> "配送中";
                case "delivered" -> "待确认收货";
                case "completed" -> "已完成";
                case "cancelled" -> "已取消";
                case "refunding" -> "退款中";
                case "refunded" -> "已退款";
                case "ready_for_pickup" -> "待自提";
                default -> "未知";
            };
        }
    }
}